package main

import (
    "bufio"
    "fmt"
    "io"
    "os/exec"
    "strings"
    "sync"
	"context"
	"time"
)

func main() {
    // 示例1: 执行简单 Linux 命令
    executeSimpleCommand()
    
    // 示例2: 实时处理输出
    processOutputInRealTime()
    
    // 示例3: 使用管道连接多个 Linux 命令
    pipeMultipleCommands()
    
    // 示例4: 处理长时间运行的进程
    longRunningProcess()
}

// 示例1: 执行简单 Linux 命令
func executeSimpleCommand() {
    fmt.Println("=== 示例1: 执行简单 Linux 命令 ===")
    
    // 创建 Linux 命令
    cmd := exec.Command("ls", "-la", "/tmp")
    
    // 执行命令并获取输出
    output, err := cmd.Output()
    if err != nil {
        fmt.Printf("命令执行错误: %v\n", err)
        return
    }
    
    fmt.Printf("命令输出:\n%s\n", string(output))
}

// 示例2: 实时处理输出行
func processOutputInRealTime() {
    fmt.Println("\n=== 示例2: 实时处理输出 ===")
    
    // 创建 Linux 命令
    cmd := exec.Command("find", "/var/log", "-name", "*.log", "-type", "f")
    
    // 获取标准输出管道
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Printf("创建输出管道错误: %v\n", err)
        return
    }
    
    // 启动命令
    if err := cmd.Start(); err != nil {
        fmt.Printf("启动命令错误: %v\n", err)
        return
    }
    
    // 创建扫描器实时读取输出
    scanner := bufio.NewScanner(stdout)
    fileCount := 0
    
    for scanner.Scan() {
        line := scanner.Text()
        fileCount++
        fmt.Printf("找到日志文件 %d: %s\n", fileCount, line)
        
        // 实时处理逻辑
        if strings.Contains(line, "error") {
            fmt.Printf("  → 可能包含错误日志: %s\n", line)
        }
    }
    
    // 检查扫描错误
    if err := scanner.Err(); err != nil {
        fmt.Printf("读取输出错误: %v\n", err)
    }
    
    // 等待命令完成
    if err := cmd.Wait(); err != nil {
        fmt.Printf("命令执行错误: %v\n", err)
    }
    
    fmt.Printf("总共找到 %d 个日志文件\n", fileCount)
}

// 示例4: 使用管道连接多个 Linux 命令
func pipeMultipleCommands() {
    fmt.Println("\n=== 示例4: 管道连接多个 Linux 命令 ===")
    
    // 创建第一个命令: 列出进程
    cmd1 := exec.Command("ps", "aux")
    
    // 创建第二个命令: 过滤包含 "nginx" 的进程
    cmd2 := exec.Command("grep", "nginx")
    
    // 创建第三个命令: 统计行数
    cmd3 := exec.Command("wc", "-l")
    
    // 连接管道: cmd1 -> cmd2 -> cmd3
    var err error
    
    // cmd2 的输入来自 cmd1 的输出
    cmd2.Stdin, err = cmd1.StdoutPipe()
    if err != nil {
        fmt.Printf("创建管道1错误: %v\n", err)
        return
    }
    
    // cmd3 的输入来自 cmd2 的输出
    cmd3.Stdin, err = cmd2.StdoutPipe()
    if err != nil {
        fmt.Printf("创建管道2错误: %v\n", err)
        return
    }
    
    // 获取 cmd3 的输出
    stdout, err := cmd3.StdoutPipe()
    if err != nil {
        fmt.Printf("创建输出管道错误: %v\n", err)
        return
    }
    
    // 启动 cmd3
    if err := cmd3.Start(); err != nil {
        fmt.Printf("启动 cmd3 错误: %v\n", err)
        return
    }
    
    // 启动 cmd2
    if err := cmd2.Start(); err != nil {
        fmt.Printf("启动 cmd2 错误: %v\n", err)
        return
    }
    
    // 启动 cmd1
    if err := cmd1.Start(); err != nil {
        fmt.Printf("启动 cmd1 错误: %v\n", err)
        return
    }
    
    // 读取 cmd3 的输出
    output, _ := io.ReadAll(stdout)
    fmt.Printf("Nginx 进程数量: %s", string(output))
    
    // 等待所有命令完成
    cmd1.Wait()
    cmd2.Wait()
    cmd3.Wait()
}

// 使用 shell 管道语法（更简单的方式）
func pipeWithShell() {
    fmt.Println("\n=== 使用 Shell 管道 ===")
    
    // 使用 bash -c 执行管道命令
    cmd := exec.Command("bash", "-c", "ps aux | grep nginx | grep -v grep | wc -l")
    
    output, err := cmd.Output()
    if err != nil {
        fmt.Printf("命令执行错误: %v\n", err)
        return
    }
    
    fmt.Printf("Nginx 进程数量: %s", string(output))
}

func longRunningProcess() {
    fmt.Println("\n=== 长时间运行进程监控示例 ===")
    
    // 启动一个长时间运行的进程（监控系统日志）
    cmd := exec.Command("tail", "-f", "/var/log/syslog")
    
    // 获取输出管道
    stdout, err := cmd.StdoutPipe()
    if err != nil {
        fmt.Printf("创建输出管道错误: %v\n", err)
        return
    }
    
    // 启动命令
    if err := cmd.Start(); err != nil {
        fmt.Printf("启动命令错误: %v\n", err)
        return
    }
    
    fmt.Printf("开始监控系统日志 (PID: %d)\n", cmd.Process.Pid)
    fmt.Println("监控将持续30秒，按Ctrl+C可提前终止")
    
    // 创建带超时的上下文
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    
    var wg sync.WaitGroup
    wg.Add(1)
    
    // 启动输出监控goroutine
    go func() {
        defer wg.Done()
        monitorProcessOutput(ctx, stdout, cmd.Process.Pid)
    }()
    
    // 等待超时或完成
    <-ctx.Done()
    fmt.Println("\n监控时间到，停止进程...")
    
    // 终止进程
    if err := cmd.Process.Kill(); err != nil {
        fmt.Printf("终止进程错误: %v\n", err)
    }
    
    // 等待输出处理完成
    wg.Wait()
    fmt.Println("监控结束")
}

// 监控进程输出
func monitorProcessOutput(ctx context.Context, reader io.Reader, pid int) {
    scanner := bufio.NewScanner(reader)
    lineCount := 0
    lastPrint := time.Now()
    
    for scanner.Scan() {
        select {
        case <-ctx.Done():
            return // 上下文取消，退出监控
        default:
            line := scanner.Text()
            lineCount++
            
            // 限制输出频率，避免刷屏
            if time.Since(lastPrint) > 2*time.Second {
                timestamp := time.Now().Format("15:04:05")
                fmt.Printf("[%s] PID%d 日志行%d: %.100s...\n", 
                    timestamp, pid, lineCount, line)
                lastPrint = time.Now()
            }
            
            // 可以在这里添加业务逻辑处理
            processLogLine(line, lineCount)
        }
    }
    
    if err := scanner.Err(); err != nil {
        fmt.Printf("读取输出错误: %v\n", err)
    }
}

// 处理日志行的业务逻辑
func processLogLine(line string, lineNum int) {
    // 示例：检测关键日志事件
    keywords := []string{"error", "warning", "failed", "exception"}
    
    for _, keyword := range keywords {
        if containsIgnoreCase(line, keyword) {
            fmt.Printf("⚠️  检测到关键词 '%s' 在行 %d\n", keyword, lineNum)
            break
        }
    }
}

// 不区分大小写的包含检查
func containsIgnoreCase(s, substr string) bool {
    // 简化实现，实际项目中可以使用 strings.Contains 和 strings.ToLower
    return len(s) >= len(substr) && 
           (s[:len(substr)] == substr || 
            len(s) > len(substr) && containsIgnoreCase(s[1:], substr))
}